﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Graphics;
using Newtonsoft.Json;
using Steamworks;
using Terraria.GameContent.UI;
using Terraria.GameContent.UI.Elements;
using Terraria.GameInput;
using Terraria.Localization;
using Terraria.ModLoader.Audio;
using Terraria.ModLoader.Default;
using Terraria.ModLoader.Exceptions;
using Terraria.ModLoader.IO;
using Terraria.ModLoader.UI;
using Terraria.UI;

namespace Terraria.ModLoader
{
	// Token: 0x020001DC RID: 476
	public static class ModLoader
	{
		// Token: 0x17000174 RID: 372
		// (get) Token: 0x060013F1 RID: 5105 RVA: 0x000100AE File Offset: 0x0000E2AE
		public static string ModPath
		{
			get
			{
				return ModLoader.modPath;
			}
		}

		// Token: 0x17000175 RID: 373
		// (get) Token: 0x060013F2 RID: 5106 RVA: 0x00410EF0 File Offset: 0x0040F0F0
		// (set) Token: 0x060013F3 RID: 5107 RVA: 0x000100B5 File Offset: 0x0000E2B5
		internal static string SteamID64
		{
			get
			{
				return SteamUser.GetSteamID().ToString();
			}
			set
			{
				ModLoader.steamID64 = value;
			}
		}

		// Token: 0x17000176 RID: 374
		// (get) Token: 0x060013F4 RID: 5108 RVA: 0x000100BD File Offset: 0x0000E2BD
		public static int ModCount
		{
			get
			{
				return ModLoader.loadedMods.Length;
			}
		}

		// Token: 0x060013F5 RID: 5109 RVA: 0x00410F10 File Offset: 0x0040F110
		public static Mod GetMod(string name)
		{
			Mod result;
			ModLoader.mods.TryGetValue(name, out result);
			return result;
		}

		// Token: 0x060013F6 RID: 5110 RVA: 0x000100C6 File Offset: 0x0000E2C6
		public static Mod GetMod(int index)
		{
			if (index < 0 || index >= ModLoader.loadedMods.Length)
			{
				return null;
			}
			return ModLoader.loadedMods[index];
		}

		// Token: 0x17000177 RID: 375
		// (get) Token: 0x060013F7 RID: 5111 RVA: 0x000100DF File Offset: 0x0000E2DF
		public static Mod[] LoadedMods
		{
			get
			{
				return (Mod[])ModLoader.loadedMods.Clone();
			}
		}

		// Token: 0x060013F8 RID: 5112 RVA: 0x000100F0 File Offset: 0x0000E2F0
		public static string[] GetLoadedMods()
		{
			return ModLoader.loadOrder.ToArray();
		}

		// Token: 0x060013F9 RID: 5113 RVA: 0x000100FC File Offset: 0x0000E2FC
		internal static void Load()
		{
			ThreadPool.QueueUserWorkItem(new WaitCallback(ModLoader.do_Load), 1);
		}

		// Token: 0x060013FA RID: 5114 RVA: 0x00410F2C File Offset: 0x0040F12C
		internal static void do_Load(object threadContext)
		{
			if (!ModLoader.LoadMods())
			{
				Main.menuMode = 10005;
				return;
			}
			if (Main.dedServ)
			{
				Console.WriteLine(Language.GetTextValue("tModLoader.AddingModContent"));
			}
			int num = 0;
			foreach (Mod mod in ModLoader.mods.Values)
			{
				Interface.loadMods.SetProgressInit(mod.Name, num, ModLoader.mods.Count);
				try
				{
					mod.loading = true;
					TmodFile file = mod.File;
					if (file != null)
					{
						file.Read(TmodFile.LoadedState.Streaming, new TmodFile.ReadStreamingAsset(mod.LoadResourceFromStream));
					}
					mod.Autoload();
					Interface.loadMods.SetSubProgressInit("");
					mod.Load();
					mod.loading = false;
				}
				catch (Exception e)
				{
					ModLoader.DisableMod(mod.Name);
					ErrorLogger.LogLoadingError(mod.Name, mod.tModLoaderVersion, e, false);
					Main.menuMode = 10005;
					return;
				}
				num++;
			}
			Interface.loadMods.SetProgressSetup(0f);
			ModLoader.ResizeArrays(false);
			RecipeGroupHelper.FixRecipeGroupLookups();
			num = 0;
			foreach (Mod mod2 in ModLoader.mods.Values)
			{
				Interface.loadMods.SetProgressLoad(mod2.Name, num, ModLoader.mods.Count);
				try
				{
					mod2.SetupContent();
					mod2.PostSetupContent();
					TmodFile file2 = mod2.File;
					if (file2 != null)
					{
						file2.UnloadAssets();
					}
				}
				catch (Exception e2)
				{
					ModLoader.DisableMod(mod2.Name);
					ErrorLogger.LogLoadingError(mod2.Name, mod2.tModLoaderVersion, e2, false);
					Main.menuMode = 10005;
					return;
				}
				num++;
			}
			ModLoader.RefreshModLanguage(Language.ActiveCulture);
			if (Main.dedServ)
			{
				ModNet.AssignNetIDs();
			}
			Main.player[255] = new Player(false);
			MapLoader.SetupModMap();
			ItemSorting.SetupWhiteLists();
			Interface.loadMods.SetProgressRecipes();
			for (int i = 0; i < Recipe.maxRecipes; i++)
			{
				Main.recipe[i] = new Recipe();
			}
			Recipe.numRecipes = 0;
			RecipeGroupHelper.ResetRecipeGroups();
			try
			{
				Recipe.SetupRecipes();
			}
			catch (AddRecipesException ex)
			{
				ErrorLogger.LogLoadingError(ex.modName, ModLoader.version, ex.InnerException, true);
				Main.menuMode = 10005;
				return;
			}
			if (ModLoader.PostLoad != null)
			{
				ModLoader.PostLoad();
				ModLoader.PostLoad = null;
			}
			else
			{
				Main.menuMode = 0;
			}
			PlayerInput.ReInitialize();
		}

		// Token: 0x060013FB RID: 5115 RVA: 0x004111F0 File Offset: 0x0040F3F0
		private static void ResizeArrays(bool unloading = false)
		{
			ItemLoader.ResizeArrays(unloading);
			EquipLoader.ResizeAndFillArrays();
			ModPrefix.ResizeArrays();
			Main.InitializeItemAnimations();
			ModDust.ResizeArrays();
			TileLoader.ResizeArrays(unloading);
			WallLoader.ResizeArrays(unloading);
			ProjectileLoader.ResizeArrays();
			NPCLoader.ResizeArrays(unloading);
			NPCHeadLoader.ResizeAndFillArrays();
			ModGore.ResizeAndFillArrays();
			SoundLoader.ResizeAndFillArrays();
			MountLoader.ResizeArrays();
			BuffLoader.ResizeArrays();
			PlayerHooks.RebuildHooks();
			BackgroundTextureLoader.ResizeAndFillArrays();
			UgBgStyleLoader.ResizeAndFillArrays();
			SurfaceBgStyleLoader.ResizeAndFillArrays();
			GlobalBgStyleLoader.ResizeAndFillArrays(unloading);
			WaterStyleLoader.ResizeArrays();
			WaterfallStyleLoader.ResizeArrays();
			WorldHooks.ResizeArrays();
			foreach (LocalizedText localizedText in LanguageManager.Instance._localizedTexts.Values)
			{
				localizedText.Override = null;
			}
		}

		// Token: 0x060013FC RID: 5116 RVA: 0x004112C0 File Offset: 0x0040F4C0
		public static void RefreshModLanguage(GameCulture culture)
		{
			Dictionary<string, LocalizedText> localizedTexts = LanguageManager.Instance._localizedTexts;
			foreach (ModItem modItem in ItemLoader.items)
			{
				LocalizedText localizedText = new LocalizedText(modItem.DisplayName.Key, modItem.DisplayName.GetTranslation(culture));
				Lang._itemNameCache[modItem.item.type] = ModLoader.SetLocalizedText(localizedTexts, localizedText);
				localizedText = new LocalizedText(modItem.Tooltip.Key, modItem.Tooltip.GetTranslation(culture));
				if (localizedText.Value != null)
				{
					localizedText = ModLoader.SetLocalizedText(localizedTexts, localizedText);
					Lang._itemTooltipCache[modItem.item.type] = ItemTooltip.FromLanguageKey(localizedText.Key);
				}
			}
			foreach (ModPrefix modPrefix in ModPrefix.prefixes)
			{
				LocalizedText value = new LocalizedText(modPrefix.DisplayName.Key, modPrefix.DisplayName.GetTranslation(culture));
				Lang.prefix[(int)modPrefix.Type] = ModLoader.SetLocalizedText(localizedTexts, value);
			}
			foreach (KeyValuePair<ushort, IList<MapEntry>> keyValuePair in MapLoader.tileEntries)
			{
				foreach (MapEntry mapEntry in keyValuePair.Value)
				{
					if (mapEntry.translation != null)
					{
						LocalizedText value2 = new LocalizedText(mapEntry.translation.Key, mapEntry.translation.GetTranslation(culture));
						ModLoader.SetLocalizedText(localizedTexts, value2);
					}
				}
			}
			foreach (KeyValuePair<ushort, IList<MapEntry>> keyValuePair2 in MapLoader.wallEntries)
			{
				foreach (MapEntry mapEntry2 in keyValuePair2.Value)
				{
					if (mapEntry2.translation != null)
					{
						LocalizedText value3 = new LocalizedText(mapEntry2.translation.Key, mapEntry2.translation.GetTranslation(culture));
						ModLoader.SetLocalizedText(localizedTexts, value3);
					}
				}
			}
			foreach (ModProjectile modProjectile in ProjectileLoader.projectiles)
			{
				LocalizedText value4 = new LocalizedText(modProjectile.DisplayName.Key, modProjectile.DisplayName.GetTranslation(culture));
				Lang._projectileNameCache[modProjectile.projectile.type] = ModLoader.SetLocalizedText(localizedTexts, value4);
			}
			foreach (ModNPC modNPC in NPCLoader.npcs)
			{
				LocalizedText value5 = new LocalizedText(modNPC.DisplayName.Key, modNPC.DisplayName.GetTranslation(culture));
				Lang._npcNameCache[modNPC.npc.type] = ModLoader.SetLocalizedText(localizedTexts, value5);
			}
			foreach (ModBuff modBuff in BuffLoader.buffs)
			{
				LocalizedText value6 = new LocalizedText(modBuff.DisplayName.Key, modBuff.DisplayName.GetTranslation(culture));
				Lang._buffNameCache[modBuff.Type] = ModLoader.SetLocalizedText(localizedTexts, value6);
				value6 = new LocalizedText(modBuff.Description.Key, modBuff.Description.GetTranslation(culture));
				Lang._buffDescriptionCache[modBuff.Type] = ModLoader.SetLocalizedText(localizedTexts, value6);
			}
			foreach (Mod mod in ModLoader.loadedMods)
			{
				foreach (ModTranslation modTranslation in mod.translations.Values)
				{
					LocalizedText value7 = new LocalizedText(modTranslation.Key, modTranslation.GetTranslation(culture));
					ModLoader.SetLocalizedText(localizedTexts, value7);
				}
			}
			LanguageManager.Instance.ProcessCopyCommandsInTexts();
		}

		// Token: 0x060013FD RID: 5117 RVA: 0x0041176C File Offset: 0x0040F96C
		private static LocalizedText SetLocalizedText(Dictionary<string, LocalizedText> dict, LocalizedText value)
		{
			if (dict.ContainsKey(value.Key))
			{
				dict[value.Key].SetValue(value.Value);
			}
			else
			{
				dict[value.Key] = value;
			}
			return dict[value.Key];
		}

		// Token: 0x060013FE RID: 5118 RVA: 0x004117BC File Offset: 0x0040F9BC
		internal static LocalMod[] FindMods()
		{
			Directory.CreateDirectory(ModLoader.ModPath);
			List<LocalMod> list = new List<LocalMod>();
			foreach (string text in Directory.GetFiles(ModLoader.ModPath, "*.tmod", SearchOption.TopDirectoryOnly))
			{
				if (!(Path.GetFileName(text) == "temporaryDownload.tmod"))
				{
					DateTime lastWriteTime = File.GetLastWriteTime(text);
					LocalMod localMod;
					if (!ModLoader.modsDirCache.TryGetValue(text, out localMod) || localMod.lastModified != lastWriteTime)
					{
						TmodFile tmodFile = new TmodFile(text);
						try
						{
							tmodFile.Read(TmodFile.LoadedState.Info, null);
						}
						catch (Exception ex)
						{
							goto IL_A0;
						}
						localMod = new LocalMod(tmodFile)
						{
							lastModified = lastWriteTime
						};
						ModLoader.modsDirCache[text] = localMod;
					}
					list.Add(localMod);
				}
				IL_A0:;
			}
			return list.OrderBy((LocalMod x) => x.Name, StringComparer.InvariantCulture).ToArray<LocalMod>();
		}

		// Token: 0x060013FF RID: 5119 RVA: 0x004118B8 File Offset: 0x0040FAB8
		private static bool LoadMods()
		{
			ModCompile.LoadReferences();
			if (!ModLoader.CommandLineModPackOverride())
			{
				return false;
			}
			Interface.loadMods.SetProgressFinding();
			List<LocalMod> list = (from mod in ModLoader.FindMods()
			where ModLoader.IsEnabled(mod.Name) && ModLoader.LoadSide(mod.properties.side)
			select mod).ToList<LocalMod>();
			if (Main.oldKeyState.PressingShift())
			{
				list.Clear();
			}
			if (!ModLoader.VerifyNames(list))
			{
				return false;
			}
			try
			{
				ModLoader.EnsureDependenciesExist(list, false);
				ModLoader.EnsureTargetVersionsMet(list);
				list = ModLoader.Sort(list);
			}
			catch (ModSortingException ex)
			{
				foreach (LocalMod localMod in ex.errored)
				{
					localMod.Enabled = false;
				}
				ErrorLogger.LogDependencyError(ex.Message);
				return false;
			}
			List<Mod> list2 = AssemblyManager.InstantiateMods(list);
			if (list2 == null)
			{
				return false;
			}
			list2.Insert(0, new ModLoaderMod());
			ModLoader.loadedMods = list2.ToArray();
			ModLoader.loadedModsWeakReferences = (from x in ModLoader.loadedMods.Skip(1)
			select new WeakReference(x)).ToArray<WeakReference>();
			foreach (Mod mod2 in list2)
			{
				ModLoader.loadOrder.Push(mod2.Name);
				ModLoader.mods[mod2.Name] = mod2;
			}
			return true;
		}

		// Token: 0x06001400 RID: 5120 RVA: 0x00411A60 File Offset: 0x0040FC60
		private static bool CommandLineModPackOverride()
		{
			if (ModLoader.commandLineModPack == "")
			{
				return true;
			}
			if (!ModLoader.commandLineModPack.EndsWith(".json"))
			{
				ModLoader.commandLineModPack += ".json";
			}
			string text = Path.Combine(UIModPacks.ModListSaveDirectory, ModLoader.commandLineModPack);
			bool result;
			try
			{
				Directory.CreateDirectory(UIModPacks.ModListSaveDirectory);
				Console.WriteLine(Language.GetTextValue("tModLoader.LoadingSpecifiedModPack", ModLoader.commandLineModPack) + "\n");
				HashSet<string> hashSet = JsonConvert.DeserializeObject<HashSet<string>>(File.ReadAllText(text));
				foreach (LocalMod localMod in ModLoader.FindMods())
				{
					ModLoader.SetModEnabled(localMod.Name, hashSet.Contains(localMod.Name));
				}
				result = true;
			}
			catch (Exception ex)
			{
				string text2;
				if (ex is FileNotFoundException)
				{
					text2 = Language.GetTextValue("tModLoader.ModPackDoesNotExist", text) + "\n";
				}
				else
				{
					text2 = Language.GetTextValue("tModLoader.ModPackDoesNotExist", ModLoader.commandLineModPack, ex.Message) + "\n";
				}
				if (Main.dedServ)
				{
					Console.ForegroundColor = ConsoleColor.Red;
					Console.WriteLine(text2);
					Console.ResetColor();
				}
				else
				{
					Interface.errorMessage.SetMessage(text2);
				}
				result = false;
			}
			finally
			{
				ModLoader.commandLineModPack = "";
			}
			return result;
		}

		// Token: 0x06001401 RID: 5121 RVA: 0x00411BC0 File Offset: 0x0040FDC0
		public static bool IsSignedBy(TmodFile mod, string xmlPublicKey)
		{
			RSAPKCS1SignatureDeformatter rsapkcs1SignatureDeformatter = new RSAPKCS1SignatureDeformatter();
			AsymmetricAlgorithm asymmetricAlgorithm = AsymmetricAlgorithm.Create("RSA");
			rsapkcs1SignatureDeformatter.SetHashAlgorithm("SHA1");
			asymmetricAlgorithm.FromXmlString(xmlPublicKey);
			rsapkcs1SignatureDeformatter.SetKey(asymmetricAlgorithm);
			return rsapkcs1SignatureDeformatter.VerifySignature(mod.hash, mod.signature);
		}

		// Token: 0x06001402 RID: 5122 RVA: 0x00411C0C File Offset: 0x0040FE0C
		private static bool VerifyNames(List<LocalMod> mods)
		{
			HashSet<string> hashSet = new HashSet<string>();
			foreach (LocalMod localMod in mods)
			{
				try
				{
					if (localMod.Name.Length == 0)
					{
						throw new ModNameException(Language.GetTextValue("tModLoader.BuildErrorModNameEmpty"));
					}
					if (localMod.Name.Equals("Terraria", StringComparison.InvariantCultureIgnoreCase))
					{
						throw new ModNameException(Language.GetTextValue("tModLoader.BuildErrorModNamedTerraria"));
					}
					if (hashSet.Contains(localMod.Name))
					{
						throw new ModNameException(Language.GetTextValue("tModLoader.BuildErrorTwoModsSameName", localMod.Name));
					}
					if (localMod.Name.IndexOf('.') >= 0)
					{
						throw new ModNameException(Language.GetTextValue("tModLoader.BuildErrorModNameHasPeriod"));
					}
					hashSet.Add(localMod.Name);
				}
				catch (Exception e)
				{
					localMod.Enabled = false;
					ErrorLogger.LogLoadingError(localMod.Name, localMod.modFile.tModLoaderVersion, e, false);
					return false;
				}
			}
			return true;
		}

		// Token: 0x06001403 RID: 5123 RVA: 0x00411D28 File Offset: 0x0040FF28
		internal static void EnsureDependenciesExist(ICollection<LocalMod> mods, bool includeWeak)
		{
			Dictionary<string, LocalMod> dictionary = mods.ToDictionary((LocalMod mod) => mod.Name);
			HashSet<LocalMod> hashSet = new HashSet<LocalMod>();
			StringBuilder stringBuilder = new StringBuilder();
			foreach (LocalMod localMod in mods)
			{
				foreach (string text in localMod.properties.RefNames(includeWeak))
				{
					if (!dictionary.ContainsKey(text))
					{
						hashSet.Add(localMod);
						stringBuilder.AppendLine(Language.GetTextValue("tModLoader.LoadErrorDependencyMissing", text, localMod));
					}
				}
			}
			if (hashSet.Count > 0)
			{
				throw new ModSortingException(hashSet, stringBuilder.ToString());
			}
		}

		// Token: 0x06001404 RID: 5124 RVA: 0x00411E1C File Offset: 0x0041001C
		internal static void EnsureTargetVersionsMet(ICollection<LocalMod> mods)
		{
			Dictionary<string, LocalMod> dictionary = mods.ToDictionary((LocalMod mod) => mod.Name);
			HashSet<LocalMod> hashSet = new HashSet<LocalMod>();
			StringBuilder stringBuilder = new StringBuilder();
			foreach (LocalMod localMod in mods)
			{
				foreach (BuildProperties.ModReference modReference in localMod.properties.Refs(true))
				{
					LocalMod localMod2;
					if (dictionary.TryGetValue(modReference.mod, out localMod2) && localMod2.properties.version < modReference.target)
					{
						hashSet.Add(localMod);
						stringBuilder.AppendLine(Language.GetTextValue("tModLoader.LoadErrorDependencyVersionTooLow", new object[]
						{
							localMod,
							modReference.target,
							modReference.mod,
							localMod2.properties.version
						}));
					}
				}
			}
			if (hashSet.Count > 0)
			{
				throw new ModSortingException(hashSet, stringBuilder.ToString());
			}
		}

		// Token: 0x06001405 RID: 5125 RVA: 0x00411F64 File Offset: 0x00410164
		internal static void EnsureSyncedDependencyStability(TopoSort<LocalMod> synced, TopoSort<LocalMod> full)
		{
			HashSet<LocalMod> hashSet = new HashSet<LocalMod>();
			StringBuilder stringBuilder = new StringBuilder();
			foreach (LocalMod localMod in synced.list)
			{
				List<List<LocalMod>> chains = new List<List<LocalMod>>();
				Action<LocalMod, Stack<LocalMod>> FindChains = null;
				FindChains = delegate(LocalMod search, Stack<LocalMod> stack)
				{
					stack.Push(search);
					if (search.properties.side == ModSide.Both && stack.Count > 1)
					{
						if (stack.Count > 2)
						{
							chains.Add(stack.Reverse<LocalMod>().ToList<LocalMod>());
						}
					}
					else
					{
						foreach (LocalMod arg in full.Dependencies(search))
						{
							FindChains(arg, stack);
						}
					}
					stack.Pop();
				};
				FindChains(localMod, new Stack<LocalMod>());
				if (chains.Count != 0)
				{
					ISet<LocalMod> set = synced.AllDependencies(localMod);
					foreach (List<LocalMod> list in chains)
					{
						if (!set.Contains(list.Last<LocalMod>()))
						{
							hashSet.Add(localMod);
							stringBuilder.AppendLine(string.Concat(new object[]
							{
								localMod,
								" indirectly depends on ",
								list.Last<LocalMod>(),
								" via ",
								string.Join<LocalMod>(" -> ", list)
							}));
						}
					}
				}
			}
			if (hashSet.Count > 0)
			{
				stringBuilder.AppendLine("Some of these mods may not exist on both client and server. Add a direct sort entries or weak references.");
				throw new ModSortingException(hashSet, stringBuilder.ToString());
			}
		}

		// Token: 0x06001406 RID: 5126 RVA: 0x00412100 File Offset: 0x00410300
		private static TopoSort<LocalMod> BuildSort(ICollection<LocalMod> mods)
		{
			Dictionary<string, LocalMod> nameMap = mods.ToDictionary((LocalMod mod) => mod.Name);
			Func<string, LocalMod> <>9__3;
			Func<string, LocalMod> <>9__4;
			return new TopoSort<LocalMod>(mods, delegate(LocalMod mod)
			{
				IEnumerable<string> source = mod.properties.sortAfter.Where(new Func<string, bool>(nameMap.ContainsKey));
				Func<string, LocalMod> selector;
				if ((selector = <>9__3) == null)
				{
					selector = (<>9__3 = ((string name) => nameMap[name]));
				}
				return source.Select(selector);
			}, delegate(LocalMod mod)
			{
				IEnumerable<string> source = mod.properties.sortBefore.Where(new Func<string, bool>(nameMap.ContainsKey));
				Func<string, LocalMod> selector;
				if ((selector = <>9__4) == null)
				{
					selector = (<>9__4 = ((string name) => nameMap[name]));
				}
				return source.Select(selector);
			});
		}

		// Token: 0x06001407 RID: 5127 RVA: 0x0041215C File Offset: 0x0041035C
		internal static List<LocalMod> Sort(ICollection<LocalMod> mods)
		{
			List<LocalMod> source = (from mod in mods
			orderby mod.Name
			select mod).ToList<LocalMod>();
			TopoSort<LocalMod> topoSort = ModLoader.BuildSort((from mod in source
			where mod.properties.side == ModSide.Both
			select mod).ToList<LocalMod>());
			TopoSort<LocalMod> topoSort2 = ModLoader.BuildSort(source);
			ModLoader.EnsureSyncedDependencyStability(topoSort, topoSort2);
			List<LocalMod> result;
			try
			{
				List<LocalMod> list = topoSort.Sort();
				for (int i = 1; i < list.Count; i++)
				{
					topoSort2.AddEntry(list[i - 1], list[i]);
				}
				result = topoSort2.Sort();
			}
			catch (TopoSort<LocalMod>.SortingException ex)
			{
				throw new ModSortingException(ex.set, ex.Message);
			}
			return result;
		}

		// Token: 0x06001408 RID: 5128 RVA: 0x00412238 File Offset: 0x00410438
		internal static void Unload()
		{
			while (ModLoader.loadOrder.Count > 0)
			{
				ModLoader.GetMod(ModLoader.loadOrder.Pop()).UnloadContent();
			}
			ModLoader.loadOrder.Clear();
			ModLoader.loadedMods = new Mod[0];
			ItemLoader.Unload();
			EquipLoader.Unload();
			ModPrefix.Unload();
			ModDust.Unload();
			TileLoader.Unload();
			ModTileEntity.Unload();
			WallLoader.Unload();
			ProjectileLoader.Unload();
			NPCLoader.Unload();
			NPCHeadLoader.Unload();
			PlayerHooks.Unload();
			BuffLoader.Unload();
			MountLoader.Unload();
			ModGore.Unload();
			SoundLoader.Unload();
			ModLoader.DisposeMusic();
			BackgroundTextureLoader.Unload();
			UgBgStyleLoader.Unload();
			SurfaceBgStyleLoader.Unload();
			GlobalBgStyleLoader.Unload();
			WaterStyleLoader.Unload();
			WaterfallStyleLoader.Unload();
			ModLoader.mods.Clear();
			WorldHooks.Unload();
			ModLoader.ResizeArrays(true);
			for (int i = 0; i < Recipe.maxRecipes; i++)
			{
				Main.recipe[i] = new Recipe();
			}
			Recipe.numRecipes = 0;
			RecipeGroupHelper.ResetRecipeGroups();
			Recipe.SetupRecipes();
			MapLoader.UnloadModMap();
			ItemSorting.SetupWhiteLists();
			ModLoader.modHotKeys.Clear();
			RecipeHooks.Unload();
			CommandManager.Unload();
			TagSerializer.Reload();
			ModNet.Unload();
			CustomCurrencyManager.Initialize();
			ModLoader.CleanupModReferences();
			if (!Main.dedServ && Main.netMode != 1)
			{
				ModNet.AllowVanillaClients = false;
			}
		}

		// Token: 0x06001409 RID: 5129 RVA: 0x00412374 File Offset: 0x00410574
		internal static void CleanupModReferences()
		{
			for (int i = 0; i < 256; i++)
			{
				Main.player[i] = new Player(true);
			}
			UIList playerList = Main._characterSelectMenu._playerList;
			if (playerList != null)
			{
				playerList.Clear();
			}
			Main.PlayerList.Clear();
			foreach (NPC npc2 in Main.npc)
			{
				npc2.SetDefaults(0, -1f);
			}
			foreach (Item item2 in Main.item)
			{
				item2.SetDefaults(0, false);
			}
			Item item3 = ItemSlot.singleSlotArray[0];
			if (item3 != null)
			{
				item3.SetDefaults(0, false);
			}
			for (int l = 0; l < Main.chest.Length; l++)
			{
				Main.chest[l] = new Chest(false);
			}
			GC.Collect();
			if (ModLoader.isModder)
			{
				foreach (WeakReference weakReference in ModLoader.loadedModsWeakReferences)
				{
					if (weakReference.IsAlive)
					{
						ErrorLogger.Log((weakReference.Target as Mod).Name + " not fully unloaded during unload.");
					}
				}
			}
		}

		// Token: 0x0600140A RID: 5130 RVA: 0x0041249C File Offset: 0x0041069C
		private static void DisposeMusic()
		{
			for (int i = 0; i < Main.music.Length; i++)
			{
				MusicStreaming musicStreaming = Main.music[i] as MusicStreaming;
				if (musicStreaming != null)
				{
					if (i < 42)
					{
						Main.music[i] = Main.soundBank.GetCue("Music_" + i);
					}
					else
					{
						Main.music[i] = null;
					}
					musicStreaming.Stop(AudioStopOptions.Immediate);
					musicStreaming.Dispose();
				}
			}
		}

		// Token: 0x0600140B RID: 5131 RVA: 0x00010116 File Offset: 0x0000E316
		internal static void Reload()
		{
			ModLoader.Unload();
			Main.menuMode = 10002;
		}

		// Token: 0x0600140C RID: 5132 RVA: 0x00010127 File Offset: 0x0000E327
		internal static bool LoadSide(ModSide side)
		{
			return side != (Main.dedServ ? ModSide.Client : ModSide.Server);
		}

		// Token: 0x17000178 RID: 376
		// (get) Token: 0x0600140D RID: 5133 RVA: 0x00412510 File Offset: 0x00410710
		internal static HashSet<string> EnabledMods
		{
			get
			{
				if (ModLoader._enabledMods == null)
				{
					try
					{
						string path = ModLoader.ModPath + Path.DirectorySeparatorChar.ToString() + "enabled.json";
						ModLoader._enabledMods = JsonConvert.DeserializeObject<HashSet<string>>(File.ReadAllText(path));
					}
					catch
					{
						ModLoader._enabledMods = new HashSet<string>();
					}
				}
				return ModLoader._enabledMods;
			}
		}

		// Token: 0x0600140E RID: 5134 RVA: 0x0001013A File Offset: 0x0000E33A
		internal static bool IsEnabled(string modName)
		{
			return ModLoader.EnabledMods.Contains(modName);
		}

		// Token: 0x0600140F RID: 5135 RVA: 0x00010147 File Offset: 0x0000E347
		internal static void EnableMod(string modName)
		{
			ModLoader.SetModEnabled(modName, true);
		}

		// Token: 0x06001410 RID: 5136 RVA: 0x00010150 File Offset: 0x0000E350
		internal static void DisableMod(string modName)
		{
			ModLoader.SetModEnabled(modName, false);
		}

		// Token: 0x06001411 RID: 5137 RVA: 0x00412578 File Offset: 0x00410778
		internal static void SetModEnabled(string modName, bool active)
		{
			if (active)
			{
				ModLoader.EnabledMods.Add(modName);
			}
			else
			{
				ModLoader.EnabledMods.Remove(modName);
			}
			Directory.CreateDirectory(ModLoader.ModPath);
			string path = ModLoader.ModPath + Path.DirectorySeparatorChar.ToString() + "enabled.json";
			ModLoader._enabledMods.IntersectWith(from x in ModLoader.FindMods()
			select x.Name);
			string contents = JsonConvert.SerializeObject(ModLoader.EnabledMods, Formatting.Indented);
			File.WriteAllText(path, contents);
		}

		// Token: 0x06001412 RID: 5138 RVA: 0x00412610 File Offset: 0x00410810
		internal static string[] FindModSources()
		{
			Directory.CreateDirectory(ModLoader.ModSourcePath);
			return (from dir in Directory.GetDirectories(ModLoader.ModSourcePath, "*", SearchOption.TopDirectoryOnly)
			where new DirectoryInfo(dir).Name != ".vs"
			select dir).ToArray<string>();
		}

		// Token: 0x06001413 RID: 5139 RVA: 0x00010159 File Offset: 0x0000E359
		internal static void BuildAllMods()
		{
			ThreadPool.QueueUserWorkItem(delegate(object _)
			{
				ModLoader.PostBuildMenu(ModCompile.BuildAll(ModLoader.FindModSources(), Interface.buildMod));
			});
		}

		// Token: 0x06001414 RID: 5140 RVA: 0x00010180 File Offset: 0x0000E380
		internal static void BuildMod()
		{
			Interface.buildMod.SetProgress(0, 1);
			ThreadPool.QueueUserWorkItem(delegate(object _)
			{
				try
				{
					ModLoader.PostBuildMenu(ModCompile.Build(ModLoader.modToBuild, Interface.buildMod));
				}
				catch (Exception e)
				{
					ErrorLogger.LogException(e, "The game has crashed!");
				}
			}, 1);
		}

		// Token: 0x06001415 RID: 5141 RVA: 0x000101B9 File Offset: 0x0000E3B9
		private static void PostBuildMenu(bool success)
		{
			Main.menuMode = (success ? (ModLoader.reloadAfterBuild ? 10006 : 0) : 10005);
		}

		// Token: 0x06001416 RID: 5142 RVA: 0x00412664 File Offset: 0x00410864
		private static void SplitName(string name, out string domain, out string subName)
		{
			int num = name.IndexOf('/');
			if (num < 0)
			{
				throw new MissingResourceException("Missing mod qualifier: " + name);
			}
			domain = name.Substring(0, num);
			subName = name.Substring(num + 1);
		}

		// Token: 0x06001417 RID: 5143 RVA: 0x004126A4 File Offset: 0x004108A4
		public static byte[] GetFileBytes(string name)
		{
			string name2;
			string name3;
			ModLoader.SplitName(name, out name2, out name3);
			Mod mod = ModLoader.GetMod(name2);
			if (mod == null)
			{
				throw new MissingResourceException("Missing mod: " + name);
			}
			return mod.GetFileBytes(name3);
		}

		// Token: 0x06001418 RID: 5144 RVA: 0x004126E0 File Offset: 0x004108E0
		public static bool FileExists(string name)
		{
			if (!name.Contains('/'))
			{
				return false;
			}
			string name2;
			string name3;
			ModLoader.SplitName(name, out name2, out name3);
			Mod mod = ModLoader.GetMod(name2);
			return mod != null && mod.FileExists(name3);
		}

		// Token: 0x06001419 RID: 5145 RVA: 0x00412718 File Offset: 0x00410918
		public static Texture2D GetTexture(string name)
		{
			if (Main.dedServ)
			{
				return null;
			}
			string text;
			string text2;
			ModLoader.SplitName(name, out text, out text2);
			if (text == "Terraria")
			{
				return Main.instance.Content.Load<Texture2D>("Images" + Path.DirectorySeparatorChar.ToString() + text2);
			}
			Mod mod = ModLoader.GetMod(text);
			if (mod == null)
			{
				throw new MissingResourceException("Missing mod: " + name);
			}
			return mod.GetTexture(text2);
		}

		// Token: 0x0600141A RID: 5146 RVA: 0x00412790 File Offset: 0x00410990
		public static bool TextureExists(string name)
		{
			if (!name.Contains('/'))
			{
				return false;
			}
			string text;
			string name2;
			ModLoader.SplitName(name, out text, out name2);
			if (text == "Terraria")
			{
				return File.Exists(ModLoader.ImagePath + Path.DirectorySeparatorChar.ToString() + name + ".xnb");
			}
			Mod mod = ModLoader.GetMod(text);
			return mod != null && mod.TextureExists(name2);
		}

		// Token: 0x0600141B RID: 5147 RVA: 0x004127F8 File Offset: 0x004109F8
		public static SoundEffect GetSound(string name)
		{
			if (Main.dedServ)
			{
				return null;
			}
			string name2;
			string name3;
			ModLoader.SplitName(name, out name2, out name3);
			Mod mod = ModLoader.GetMod(name2);
			if (mod == null)
			{
				throw new MissingResourceException("Missing mod: " + name);
			}
			return mod.GetSound(name3);
		}

		// Token: 0x0600141C RID: 5148 RVA: 0x0041283C File Offset: 0x00410A3C
		public static bool SoundExists(string name)
		{
			if (!name.Contains('/'))
			{
				return false;
			}
			string name2;
			string name3;
			ModLoader.SplitName(name, out name2, out name3);
			Mod mod = ModLoader.GetMod(name2);
			return mod != null && mod.SoundExists(name3);
		}

		// Token: 0x0600141D RID: 5149 RVA: 0x00412874 File Offset: 0x00410A74
		public static Music GetMusic(string name)
		{
			if (Main.dedServ)
			{
				return null;
			}
			string name2;
			string name3;
			ModLoader.SplitName(name, out name2, out name3);
			Mod mod = ModLoader.GetMod(name2);
			if (mod == null)
			{
				throw new MissingResourceException("Missing mod: " + name);
			}
			return mod.GetMusic(name3);
		}

		// Token: 0x0600141E RID: 5150 RVA: 0x004128B8 File Offset: 0x00410AB8
		public static bool MusicExists(string name)
		{
			if (!name.Contains('/'))
			{
				return false;
			}
			string name2;
			string name3;
			ModLoader.SplitName(name, out name2, out name3);
			Mod mod = ModLoader.GetMod(name2);
			return mod != null && mod.MusicExists(name3);
		}

		// Token: 0x0600141F RID: 5151 RVA: 0x004128F0 File Offset: 0x00410AF0
		public static ModHotKey RegisterHotKey(Mod mod, string name, string defaultKey)
		{
			string key = mod.Name + ": " + name;
			ModLoader.modHotKeys[key] = new ModHotKey(mod, name, defaultKey);
			return ModLoader.modHotKeys[key];
		}

		// Token: 0x06001420 RID: 5152 RVA: 0x00412930 File Offset: 0x00410B30
		internal static void SaveConfiguration()
		{
			Main.Configuration.Put("ModBrowserPassphrase", ModLoader.modBrowserPassphrase);
			Main.Configuration.Put("SteamID64", ModLoader.steamID64);
			Main.Configuration.Put("DownloadModsFromServers", ModNet.downloadModsFromServers);
			Main.Configuration.Put("OnlyDownloadSignedModsFromServers", ModNet.onlyDownloadSignedMods);
			Main.Configuration.Put("DontRemindModBrowserUpdateReload", ModLoader.dontRemindModBrowserUpdateReload);
			Main.Configuration.Put("DontRemindModBrowserDownloadEnable", ModLoader.dontRemindModBrowserDownloadEnable);
			Main.Configuration.Put("MusicStreamMode", ModLoader.musicStreamMode);
			Main.Configuration.Put("AlwaysLogExceptions", ModLoader.alwaysLogExceptions);
		}

		// Token: 0x06001421 RID: 5153 RVA: 0x004129FC File Offset: 0x00410BFC
		internal static void LoadConfiguration()
		{
			Main.Configuration.Get<string>("ModBrowserPassphrase", ref ModLoader.modBrowserPassphrase);
			Main.Configuration.Get<string>("SteamID64", ref ModLoader.steamID64);
			Main.Configuration.Get<bool>("DownloadModsFromServers", ref ModNet.downloadModsFromServers);
			Main.Configuration.Get<bool>("OnlyDownloadSignedModsFromServers", ref ModNet.onlyDownloadSignedMods);
			Main.Configuration.Get<bool>("DontRemindModBrowserUpdateReload", ref ModLoader.dontRemindModBrowserUpdateReload);
			Main.Configuration.Get<bool>("DontRemindModBrowserDownloadEnable", ref ModLoader.dontRemindModBrowserDownloadEnable);
			Main.Configuration.Get<byte>("MusicStreamMode", ref ModLoader.musicStreamMode);
			Main.Configuration.Get<bool>("AlwaysLogExceptions", ref ModLoader.alwaysLogExceptions);
		}

		// Token: 0x06001422 RID: 5154 RVA: 0x000101D9 File Offset: 0x0000E3D9
		internal static void BuildGlobalHook<T, F>(ref F[] list, IList<T> providers, Expression<Func<T, F>> expr)
		{
			list = ModLoader.BuildGlobalHook<T, F>(providers, expr).Select(expr.Compile()).ToArray<F>();
		}

		// Token: 0x06001423 RID: 5155 RVA: 0x000101F4 File Offset: 0x0000E3F4
		internal static T[] BuildGlobalHook<T, F>(IList<T> providers, Expression<Func<T, F>> expr)
		{
			return ModLoader.BuildGlobalHook<T>(providers, ModLoader.Method<T, F>(expr));
		}

		// Token: 0x06001424 RID: 5156 RVA: 0x00412AAC File Offset: 0x00410CAC
		internal static T[] BuildGlobalHook<T>(IList<T> providers, MethodInfo method)
		{
			if (!method.IsVirtual)
			{
				throw new ArgumentException("Cannot build hook for non-virtual method " + method);
			}
			Type[] argTypes = (from p in method.GetParameters()
			select p.ParameterType).ToArray<Type>();
			return (from p in providers
			where p.GetType().GetMethod(method.Name, argTypes).DeclaringType != typeof(T)
			select p).ToArray<T>();
		}

		// Token: 0x06001425 RID: 5157 RVA: 0x00412B3C File Offset: 0x00410D3C
		internal static MethodInfo Method<T, F>(Expression<Func<T, F>> expr)
		{
			MethodInfo methodInfo;
			try
			{
				UnaryExpression unaryExpression = expr.Body as UnaryExpression;
				MethodCallExpression methodCallExpression = unaryExpression.Operand as MethodCallExpression;
				ConstantExpression constantExpression = methodCallExpression.Arguments[2] as ConstantExpression;
				methodInfo = (constantExpression.Value as MethodInfo);
				if (methodInfo == null)
				{
					throw new NullReferenceException();
				}
			}
			catch (Exception innerException)
			{
				throw new ArgumentException("Invalid hook expression " + expr, innerException);
			}
			return methodInfo;
		}

		// Token: 0x04001474 RID: 5236
		public static readonly Version version = new Version(0, 10, 1, 4);

		// Token: 0x04001475 RID: 5237
		public static readonly string versionedName = "tModLoader v" + ModLoader.version;

		// Token: 0x04001476 RID: 5238
		public static readonly bool beta = false;

		// Token: 0x04001477 RID: 5239
		public static readonly bool windows = true;

		// Token: 0x04001478 RID: 5240
		public static readonly bool linux = false;

		// Token: 0x04001479 RID: 5241
		public static readonly bool mac = false;

		// Token: 0x0400147A RID: 5242
		public static readonly bool gog = false;

		// Token: 0x0400147B RID: 5243
		public static readonly string compressedPlatformRepresentation = (ModLoader.windows ? "w" : (ModLoader.linux ? "l" : "m")) + (ModLoader.gog ? "g" : "s");

		// Token: 0x0400147C RID: 5244
		internal static string modPath = Main.SavePath + Path.DirectorySeparatorChar.ToString() + "Mods";

		// Token: 0x0400147D RID: 5245
		public static readonly string ModSourcePath = Main.SavePath + Path.DirectorySeparatorChar.ToString() + "Mod Sources";

		// Token: 0x0400147E RID: 5246
		private static readonly string ImagePath = "Content" + Path.DirectorySeparatorChar.ToString() + "Images";

		// Token: 0x0400147F RID: 5247
		internal const int earliestRelease = 149;

		// Token: 0x04001480 RID: 5248
		internal static string modToBuild;

		// Token: 0x04001481 RID: 5249
		internal static bool reloadAfterBuild = false;

		// Token: 0x04001482 RID: 5250
		internal static bool buildAll = false;

		// Token: 0x04001483 RID: 5251
		private static readonly Stack<string> loadOrder = new Stack<string>();

		// Token: 0x04001484 RID: 5252
		private static WeakReference[] loadedModsWeakReferences = new WeakReference[0];

		// Token: 0x04001485 RID: 5253
		private static Mod[] loadedMods = new Mod[0];

		// Token: 0x04001486 RID: 5254
		internal static readonly IDictionary<string, Mod> mods = new Dictionary<string, Mod>(StringComparer.OrdinalIgnoreCase);

		// Token: 0x04001487 RID: 5255
		internal static readonly IDictionary<string, ModHotKey> modHotKeys = new Dictionary<string, ModHotKey>();

		// Token: 0x04001488 RID: 5256
		internal static readonly string modBrowserPublicKey = "<RSAKeyValue><Modulus>oCZObovrqLjlgTXY/BKy72dRZhoaA6nWRSGuA+aAIzlvtcxkBK5uKev3DZzIj0X51dE/qgRS3OHkcrukqvrdKdsuluu0JmQXCv+m7sDYjPQ0E6rN4nYQhgfRn2kfSvKYWGefp+kqmMF9xoAq666YNGVoERPm3j99vA+6EIwKaeqLB24MrNMO/TIf9ysb0SSxoV8pC/5P/N6ViIOk3adSnrgGbXnFkNQwD0qsgOWDks8jbYyrxUFMc4rFmZ8lZKhikVR+AisQtPGUs3ruVh4EWbiZGM2NOkhOCOM4k1hsdBOyX2gUliD0yjK5tiU3LBqkxoi2t342hWAkNNb4ZxLotw==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>";

		// Token: 0x04001489 RID: 5257
		internal static string modBrowserPassphrase = "";

		// Token: 0x0400148A RID: 5258
		internal static bool isModder;

		// Token: 0x0400148B RID: 5259
		internal static bool alwaysLogExceptions;

		// Token: 0x0400148C RID: 5260
		internal static bool dontRemindModBrowserUpdateReload;

		// Token: 0x0400148D RID: 5261
		internal static bool dontRemindModBrowserDownloadEnable;

		// Token: 0x0400148E RID: 5262
		internal static byte musicStreamMode;

		// Token: 0x0400148F RID: 5263
		internal static string commandLineModPack = "";

		// Token: 0x04001490 RID: 5264
		private static string steamID64 = "";

		// Token: 0x04001491 RID: 5265
		internal static Action PostLoad;

		// Token: 0x04001492 RID: 5266
		internal static Dictionary<string, LocalMod> modsDirCache = new Dictionary<string, LocalMod>();

		// Token: 0x04001493 RID: 5267
		private static HashSet<string> _enabledMods;
	}
}
